﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
// 原题连接：https://leetcode.cn/problems/time-needed-to-buy-tickets/
/*
题目描述：
有 n 个人前来排队买票，其中第 0 人站在队伍 最前方 ，第 (n - 1) 人站在队伍 最后方 。

给你一个下标从 0 开始的整数数组 tickets ，数组长度为 n ，其中第 i 人想要购买的票数为 tickets[i] 。
每个人买票都需要用掉 恰好 1 秒 。一个人 一次只能买一张票 ，如果需要购买更多票，他必须走到  队尾 重新排队（瞬间 发生，不计时间）。
如果一个人没有剩下需要买的票，那他将会 离开 队伍。
返回位于位置 k（下标从 0 开始）的人完成买票需要的时间（以秒为单位）。

 

示例 1：
输入：tickets = [2,3,2], k = 2
输出：6
解释：
- 第一轮，队伍中的每个人都买到一张票，队伍变为 [1, 2, 1] 。
- 第二轮，队伍中的每个都又都买到一张票，队伍变为 [0, 1, 0] 。
位置 2 的人成功买到 2 张票，用掉 3 + 3 = 6 秒。

示例 2：
输入：tickets = [5,1,1,1], k = 0
输出：8
解释：
- 第一轮，队伍中的每个人都买到一张票，队伍变为 [4, 0, 0, 0] 。
- 接下来的 4 轮，只有位置 0 的人在买票。
位置 0 的人成功买到 5 张票，用掉 4 + 1 + 1 + 1 + 1 = 8 秒。
 

提示：
n == tickets.length
1 <= n <= 100
1 <= tickets[i] <= 100
0 <= k < n
*/

// 开始解题
// 方法1——使用队列

// 创建一个结构体，保存数组中对应的之和下标
typedef struct keyVal {
	int index;
	int val;
} keyVal;

// 先将队列实现一下
// 重定义数据类型
typedef keyVal QDataType;
// 定义节点类型
typedef struct QueueNode {
	struct QueueNode* next;
	QDataType data;
} QueueNode;
// 定义队列类型
typedef struct Queue {
	QueueNode* head;
	QueueNode* tail;
} Queue;
// 队列的初始化
void QueueInit(Queue* pq);
// 队列的入队
void QueuePush(Queue* pq, QDataType x);
// 队列的出队
void QueuePop(Queue* pq);
// 返回队列的对头元素
QDataType QueueFront(Queue* pq);
// 返回队列的队尾元素
QDataType QueueBack(Queue* pq);
// 返回队列中的节点个数
int QueueSize(Queue* pq);
// 判断队列是否为空
bool QueueEmpty(Queue* pq);
// 销毁队列
void QueueDestroy(Queue* pq);
// 队列的初始化
void QueueInit(Queue* pq) {
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}
// 队列的入队
void QueuePush(Queue* pq, QDataType x) {
	assert(pq);
	// 创建一个新节点
	QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (NULL == newNode) {
		perror("malloc fail!\n");
		exit(-1);
	}
	newNode->data = x;
	if (NULL == pq->head) {
		pq->head = newNode;
		pq->tail = newNode;
		pq->tail->next = NULL;
	}
	else {
		pq->tail->next = newNode;
		pq->tail = pq->tail->next;
		pq->tail->next = NULL;
	}
}
// 队列的出队
void QueuePop(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	QueueNode* next = pq->head->next;
	free(pq->head);
	pq->head = next;
	// 如果对头为空了，我们也要把队尾也给置空，避免野指针
	if (NULL == pq->head) {
		pq->tail = NULL;
	}
}
// 返回队列的对头元素
QDataType QueueFront(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}
// 返回队列的队尾元素
QDataType QueueBack(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}
// 返回队列中的节点个数
int QueueSize(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	QueueNode* cur = pq->head;
	int size = 0;
	while (cur) {
		size++;
		cur = cur->next;
	}
	return size;
}
// 判断队列是否为空
bool QueueEmpty(Queue* pq) {
	assert(pq);
	return pq->head == NULL;
}
// 销毁队列
void QueueDestroy(Queue* pq) {
	assert(pq);
	if (!QueueEmpty(pq)) {
		QueueNode* cur = pq->head;
		QueueNode* next = cur->next;
		while (cur) {
			next = cur->next;
			free(cur);
			cur = next;
		}
	}
	pq->head = NULL;
	pq->tail = NULL;
}



int timeRequiredToBuy(int* tickets, int ticketsSize, int k) {
	assert(tickets);
	int time = 0;
	Queue queue;
	QueueInit(&queue);
	int i = 0;
	keyVal* keyArray = (keyVal*)malloc(ticketsSize * sizeof(keyVal));
	if (NULL == keyArray) {
		perror("malloc fail!\n");
		exit(-1);
	}
	// 先完善好keyArray
	for (i = 0; i < ticketsSize; i++) {
		keyArray[i].index = i;
		keyArray[i].val = tickets[i];
	}
	// 再将keyArray中的元素入队列
	for (i = 0; i < ticketsSize; i++) {
		QueuePush(&queue, keyArray[i]);
	}

	while (1) {
		keyVal front = QueueFront(&queue);
		QueuePop(&queue);
		front.val--;
		if (front.val > 0) {
			QueuePush(&queue, front);
		}
		time++;
		if (front.index == k && front.val == 0) {
			break;
		}
	}
	QueueDestroy(&queue);
	free(keyArray);
	return time;
}

